package com.xframe.common.core.service.command;

import cn.hutool.json.JSONUtil;
import com.xframe.domain.CommandBodyContainer;
import com.xframe.domain.IExecFindAction;
import com.xframe.domain.repository.SysBaseRepository;
import com.xframe.domain.role.IUserCredentials;
import com.xframe.domain.sys.SysModel;
import com.xframe.common.core.constant.ErrorConstant;
import com.xframe.domain.CommandModel;
import com.xframe.common.core.dto.ErrorCode;
import com.xframe.common.core.exception.BusinessException;
import com.xframe.domain.ModelRepositoryFactory;

import com.xframe.xdal.core.domain.SysBaseEntity;
import com.xframe.xdal.core.exception.DalFrameException;
import com.xframe.xdal.core.model.IModel;
import com.xframe.xdal.core.util.StringUtil;
import com.xframe.xdal.core.util.XReflect;
import lombok.extern.log4j.Log4j2;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * @description:执行模型对应的方法
 * @param:
 * @return: com.xframe.common.core.service.command.ExecModelAction
 * @author: xufeng
 * @createDate: 16:05 2023/7/24
 **/
@Log4j2
public class ExecModelAction extends BaseCommand {
    @Override
    public Object ProcCommand(CommandModel requestArgs, IUserCredentials userCredentials) throws BusinessException {
        try {
            System.out.println(requestArgs);
            System.out.println(userCredentials);
            if (StringUtil.isEmpty(requestArgs.getModelCode())) {
                throw new BusinessException(ErrorCode.ARGS_NULL, ErrorConstant.MODELID_NULL_MSG);
            }
            if (StringUtil.isEmpty(requestArgs.getCommandArgs())) {
                throw new BusinessException(ErrorCode.METHOD_NAME_IS_NULL, ErrorConstant.METHOD_NAME_IS_NULL_MSG);
            }
            SysModel sysModel = SysModel.getInstance(requestArgs.getModelCode());
            if (sysModel == null) {
                throw new BusinessException(ErrorCode.DB_RECORD_NOFIND,
                        StringUtil.format(ErrorConstant.DB_RECORD_NOFIND_MSG, requestArgs.getModelCode()));
            }

            Class<?> dataType = XReflect.getClassByName(sysModel.getClassName());
            if (dataType == null) {
                throw new BusinessException(ErrorCode.DATA_TYPE_NOT_FIND, ErrorConstant.DATA_TYPE_NOT_FIND_MSG);
            }

            SysBaseRepository repository = ModelRepositoryFactory.builder(sysModel);
            Map<String, Object> dto = requestArgs.getCommandBodyByMap();

            if(dto.containsKey("ids")) {
                List<String> ids = (List<String>) dto.get("ids");
                ExceAction repositoryExceAction = getExceAction(requestArgs,repository);
                // 参数处理
                String parString = JSONUtil.toJsonStr(requestArgs.getParameter());
                List<Object> defValue = new ArrayList<>();
                defValue.add(userCredentials);
                defValue.add(requestArgs);
                defValue.add(ids);
                Object[] parArray = XReflect.createMethodParames(repositoryExceAction.getMethod(), parString,requestArgs.getCommandBodyByJSONObject(), defValue);
                // 执行
                Object resaultVal = this.execAction(repositoryExceAction.getExecObj(), repository, repositoryExceAction.getMethod(), parArray);
                log.info(resaultVal);
                return resaultVal;

            }else {
                IModel model = deserialization(sysModel, requestArgs);
                IModel domainObj = null;

                System.out.println(repository);
                if(repository instanceof IExecFindAction){
                    System.out.println(999666);
                    IExecFindAction execFindAction = (IExecFindAction)repository;
                    domainObj = execFindAction.findDataByKey(model,sysModel,dataType);
                }else {
                    domainObj = repository.findByPK(dataType, model.getObjectId(), sysModel, SysBaseEntity.FULL_DATA);
                }

                if (domainObj == null) {
                    throw new BusinessException(ErrorCode.DB_RECORD_NOFIND,
                            StringUtil.format(ErrorConstant.DB_RECORD_NOFIND_MSG, model.getObjectId()));
                }

                // 获得需要执行的方法和对象
                ExceAction exceAction = getExceAction(domainObj,requestArgs,dataType,repository);

                // 参数处理
                String parString = JSONUtil.toJsonStr(requestArgs.getParameter());
                List<Object> defValue = new ArrayList<>();
                defValue.add(userCredentials);
                defValue.add(requestArgs);
                defValue.add(repository);
                defValue.add(domainObj);
                CommandBodyContainer.addModel(model);
                Object[] parArray = XReflect.createMethodParames(exceAction.getMethod(), parString, requestArgs.getCommandBodyByJSONObject(),defValue);
                // 执行
                Object resaultVal = this.execAction(exceAction.getExecObj(), repository, exceAction.getMethod(), parArray);
                log.info(resaultVal);
                return resaultVal;
            }
        } catch (BusinessException businessException) {
            throw businessException;
        } catch (DalFrameException exception) {
            throw new BusinessException(exception.getCode(), exception.getMessage());
        } catch (Exception exception) {
            throw new BusinessException(ErrorCode.INTERNAL_SERVER_ERROR, exception.getMessage());
        }
    }


    private ExceAction getExceAction(IModel domainObj,CommandModel requestArgs,Class<?> dataType,SysBaseRepository repository){
        ExceAction exceAction = new ExceAction();
        Object execObj = domainObj;
        // 反射获得方法
        Method method = XReflect.getActionMethod(dataType, requestArgs.getCommandArgs());
        if (method == null) {
            // 在repository 上查找
            method = XReflect.getActionMethod(repository.getClass(), requestArgs.getCommandArgs());
            if (method == null) {
                throw new BusinessException(ErrorCode.METHOD_NOT_FIND,
                        StringUtil.format(ErrorConstant.METHOD_NOT_FIND_MSG, requestArgs.getCommandArgs()));
            }
            execObj = repository;
        }
        exceAction.setMethod(method);
        exceAction.setExecObj(execObj);
        return exceAction;
    }

    private ExceAction getExceAction(CommandModel requestArgs,SysBaseRepository repository){
        ExceAction exceAction = new ExceAction();
        Object execObj = repository;
        // 在repository 上查找
        Method method = XReflect.getActionMethod(repository.getClass(), requestArgs.getCommandArgs() + "ByBatch");
        if (method == null) {
            throw new BusinessException(ErrorCode.METHOD_NOT_FIND,
                    StringUtil.format(ErrorConstant.METHOD_NOT_FIND_MSG, requestArgs.getCommandArgs() + "ByBatch"));
        }
        exceAction.setMethod(method);
        exceAction.setExecObj(execObj);
        return exceAction;
    }


    @Override
    public String getBeanName() {
        return "ExecModelAction";
    }
}
